package com.spring.beanpostprocessor;

import com.spring.annotation.Transaction;
import com.spring.aop.TransactionAdvisor;
import com.spring.aware.ApplicationContextAware;
import com.spring.bean.BeanDefinition;
import com.spring.context.BeanDefinitionRegistry;
import com.spring.context.impl.AbstractApplicationContext;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;


/**
 * 类注解 会覆盖方法注解，所以 只想要某个方法增加事务，就不要在类上面加注解
 */

@Slf4j
public class TransactionBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
	
	private AbstractApplicationContext ac;
	
	private final Set<String> resolvedBeanName = new HashSet<>();
	
	public TransactionBeanDefinitionRegistryPostProcessor(AbstractApplicationContext ac) {
		this.ac = ac;
	}
	
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		// 扫描所有 bean 定义检查是否有 @Transaction 注解存在
		Collection<BeanDefinition> allBeanDefinition = registry.getAllBeanDefinition();
		for (BeanDefinition bd : allBeanDefinition) {
			if (resolvedBeanName.contains(bd.getBeanName())) {
				continue;
			}
			
			Class<?> clazz = bd.getBeanClass();
			if (clazz.isAnnotationPresent(Transaction.class)) {
				log.info("发现{}类存在@Transaction注解,添加切面信息", clazz.getName());
				TransactionAdvisor advisor = new TransactionAdvisor(clazz.getName(), "*", ac);
				ac.addAdvisor(advisor);
			} else {
				Method[] methods = clazz.getMethods();
				for (Method method : methods) {
					if (method.isAnnotationPresent(Transaction.class)) {
						log.info("发现 {} 类 {} 方法存在@Transaction注解,添加切面信息", clazz.getName(), method.getName());
						TransactionAdvisor advisor = new TransactionAdvisor(clazz.getName(), method.getName(), ac);
						ac.addAdvisor(advisor);
					}
				}
			}
			resolvedBeanName.add(bd.getBeanName());
		}
	}
}
